﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Logging;
using StyleMVVM.Validation;
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

#else
using System.Windows;
using System.Windows.Controls;

#endif

namespace StyleMVVM.View
{
	public sealed class ValidationHelper : IPropertyValidationHandler
	{
		private readonly string propertyName;
		private readonly Control view;
		private readonly IValidationContext validationContext;

		public ValidationHelper(Control element,
		                        object validationObject,
		                        string propertyName,
		                        IValidationService validationService)
		{
			this.propertyName = propertyName;

			element.Loaded += LoadedHandler;
			view = element;

			validationContext = validationService.GetValidationContext(validationObject);

			validationContext.RegisterPropertyValidationHandler(propertyName, this);
		}

		public static ValidationHelper GetHelper(DependencyObject obj)
		{
			return (ValidationHelper)obj.GetValue(HelperProperty);
		}

		public static void SetHelper(DependencyObject obj, ValidationHelper value)
		{
			obj.SetValue(HelperProperty, value);
		}

		// Using a DependencyProperty as the backing store for Helper.  This enables animation, styling, binding, etc...
		internal static readonly DependencyProperty HelperProperty =
			DependencyProperty.RegisterAttached("Helper",
			                                    typeof(ValidationHelper),
			                                    typeof(ValidationHelper),
			                                    new PropertyMetadata(null));

		private static readonly string supplemental = typeof(ValidationHelper).FullName;

		public void ProcessPropertyValidation(IEnumerable<IValidationRuleResultPart> ruleResultParts)
		{
			ValidationState state = ValidationState.Valid;
			string validationMessage = null;

			try
			{
				if (ruleResultParts != null)
				{
					foreach (IValidationRuleResultPart validationRuleResultPart in ruleResultParts)
					{
						if (validationRuleResultPart != null)
						{
							switch (validationRuleResultPart.State)
							{
								case ValidationState.ValidWithWarning:
									if (state == ValidationState.Valid)
									{
										state = ValidationState.ValidWithWarning;
									}
									validationMessage += validationRuleResultPart.Message + Environment.NewLine;
									break;
								case ValidationState.InvalidRequired:
									if (state != ValidationState.Invalid)
									{
										state = ValidationState.InvalidRequired;
									}
									validationMessage += validationRuleResultPart.Message + Environment.NewLine;
									break;
								case ValidationState.Invalid:
									state = ValidationState.Invalid;
									validationMessage += validationRuleResultPart.Message + Environment.NewLine;
									break;
							}
						}
					}
				}

				string newState = state.ToString();

				Validation.SetMessage(view, validationMessage);
				VisualStateManager.GoToState(view, newState, true);

				if (Validation.GetAssignMessageToTooltip(view))
				{
					ToolTipService.SetToolTip(view, validationMessage);
				}
			}
			catch (Exception exp)
			{
				Logger.Error("Exception thrown while transitioning control to state: " + state, supplemental, exp);
			}
		}

		public void Close()
		{
			validationContext.UnregisterPropertyValidationHandler(propertyName, this);
		}

		private void LoadedHandler(object sender, RoutedEventArgs args)
		{
			Control control = sender as Control;

			if (control != null)
			{
				control.Loaded -= LoadedHandler;

				ProcessPropertyValidation(
					validationContext.PropertyResults(propertyName));
			}
		}
	}
}